package com.codedancer.campus.manager.service.impl;

import cn.afterturn.easypoi.entity.vo.NormalExcelConstants;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.afterturn.easypoi.view.PoiBaseView;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.codedancer.campus.common.exception.BusinessException;
import com.codedancer.campus.common.utils.CodecUtils;
import com.codedancer.campus.enums.SystemMessageType;
import com.codedancer.campus.manager.mq.producer.MqSendMessageProducer;
import com.codedancer.campus.manager.service.IUserService;
import com.codedancer.campus.manager.service.bo.user.UserPageSearchBo;
import com.codedancer.campus.manager.service.bo.user.UserUpdateBo;
import com.codedancer.campus.manager.service.excel.UserExcel;
import com.codedancer.campus.manager.service.model.SystemMessageMqParamModel;
import com.codedancer.campus.manager.service.vo.user.UserInfoVo;
import com.codedancer.campus.manager.service.vo.user.UserPageVo;
import com.codedancer.campus.mapper.SchoolMapper;
import com.codedancer.campus.mapper.SystemMessageMapper;
import com.codedancer.campus.mapper.UserMapper;
import com.codedancer.campus.mapper.UserSchoolMapper;
import com.codedancer.campus.po.School;
import com.codedancer.campus.po.User;
import com.codedancer.campus.po.UserSchool;
import com.codedancer.campus.qo.user.UserPageSearchQo;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class UserServiceImpl implements IUserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserSchoolMapper userSchoolMapper;
    @Autowired
    private SchoolMapper schoolMapper;
    @Autowired
    private SystemMessageMapper systemMessageMapper;
    @Autowired
    private MqSendMessageProducer mqSendMessageProducer;

    /**
     * 分页查询用户
     *
     * @param userPageSearchBo
     * @return
     */
    @Override
    public IPage<UserPageVo> page(UserPageSearchBo userPageSearchBo) {
        UserPageSearchQo userPageSearchQo = BeanUtil.copyProperties(userPageSearchBo,
            UserPageSearchQo.class);
        IPage<User> userIPage = userMapper.page(
            new Page<User>(userPageSearchBo.getPage(), userPageSearchBo.getSize()),
            userPageSearchQo);
        IPage<UserPageVo> userPageVoIPage = new Page<>();
        List<UserPageVo> userPageVos;
        userPageVos = userIPage.getRecords().stream().map(user -> {
            UserPageVo userPageVo = BeanUtil.copyProperties(user, UserPageVo.class);
            if (ObjectUtil.isNotEmpty(user.getSchool())) {
                userPageVo.setSchoolName(user.getSchool().getName());
            }
            // 手机号脱敏
            if (ObjectUtil.isNotEmpty(user.getPhone())) {
                userPageVo.setPhone(DesensitizedUtil.mobilePhone(user.getPhone()));
            }
            return userPageVo;
        }).collect(Collectors.toList());
        userPageVoIPage.setRecords(userPageVos);
        userPageVoIPage.setTotal(userIPage.getTotal());
        return userPageVoIPage;
    }

    /**
     * 启用用户
     *
     * @param uuid 用户uuid
     */
    @Override
    public void enable(String uuid) {
        User user = userMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("用户不存在"));
        user.setDisabled(false);
        userMapper.updateById(user);
    }

    /**
     * 禁用用户
     *
     * @param uuid
     */
    @Override
    public void disable(String uuid) {
        User user = userMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("用户不存在"));
        user.setDisabled(true);
        userMapper.updateById(user);
    }

    /**
     * 删除用户
     *
     * @param uuid 用户uuid
     */
    @Override
    public void delete(String uuid) {
        if (!userMapper.existsByUuId(uuid)) {
            throw
                new BusinessException("用户不存在");
        }
        userMapper.deleteById(uuid);
    }

    /**
     * 导出用户
     *
     * @param request
     * @param response
     */
    @Override
    public void export(HttpServletRequest request, HttpServletResponse response,
        UserPageSearchBo userPageSearchBo) {
        log.info("开始导出用户数据");
        UserPageSearchQo userPageSearchQo = BeanUtil
            .copyProperties(userPageSearchBo, UserPageSearchQo.class);
        // 查询需要导出的用户数据
        List<User> users = userMapper.listExportUser(userPageSearchQo);
        // 组装数据
        List<UserExcel> userExcels = assembleData(users);
        Map<String, Object> map = new HashMap<>();
        ExportParams params = new ExportParams("用户列表", "用户列表", ExcelType.HSSF);
        map.put(NormalExcelConstants.DATA_LIST, userExcels);
        map.put(NormalExcelConstants.CLASS, UserExcel.class);
        map.put(NormalExcelConstants.PARAMS, params);
        map.put(NormalExcelConstants.FILE_NAME, "用户列表" + DateUtil.today());
        PoiBaseView.render(map, request, response, NormalExcelConstants.EASYPOI_EXCEL_VIEW);
        log.info("导出用户数据完成");
    }

    /**
     * 批量启用
     *
     * @param uuids
     */
    @Override
    public void batchEnable(List<String> uuids) {
        for (String uuid : uuids) {
            User user = userMapper.findById(uuid)
                .orElseThrow(() -> new BusinessException("用户不存在，用户Uuid：" + uuid));
            user.setDisabled(false);
            userMapper.updateById(user);
        }
    }

    /**
     * 批量禁用
     *
     * @param uuids
     */
    @Override
    public void batchDisable(List<String> uuids) {
        for (String uuid : uuids) {
            User user = userMapper.findById(uuid)
                .orElseThrow(() -> new BusinessException("用户不存在，用户Uuid：" + uuid));
            user.setDisabled(true);
            userMapper.updateById(user);
        }
    }

    /**
     * 批量删除
     *
     * @param uuids
     */
    @Override
    public void batchDelete(List<String> uuids) {
        for (String uuid : uuids) {
            if (!userMapper.existsByUuId(uuid)) {
                throw new BusinessException("用户不存在，用户Uuid：" + uuid);
            }
            userMapper.deleteById(uuid);
        }
    }

    /**
     * 用户详情
     *
     * @param uuid
     * @return
     */
    @Override
    public UserInfoVo detail(String uuid) {
        User user = userMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("用户不存在"));
        if (!user.getIsSetBasicMessage()) {
            throw new BusinessException("用户未设置基本信息");
        }
        if (user.getDisabled()) {
            throw new BusinessException("用户已被禁用");
        }
        UserInfoVo userInfoVo = BeanUtil.copyProperties(user, UserInfoVo.class);
        // 获取用户学校
        UserSchool userSchool = userSchoolMapper.selectOneByColumn("user_uuid", user.getUuid());
        userInfoVo.setSchoolUuid(userSchool.getSchoolUuid());
        return userInfoVo;
    }

    /**
     * 修改用户
     *
     * @param userUpdateBo
     */
    @Override
    public void updateUser(UserUpdateBo userUpdateBo) {
        User user = userMapper.findById(userUpdateBo.getUserUuid())
            .orElseThrow(() -> new BusinessException("用户不存在"));
        if (user.getDisabled()) {
            throw new BusinessException("用户已被禁用，不能修改");
        }
        if (!user.getIsSetBasicMessage()) {
            throw new BusinessException("用户未设置基本信息，不能修改");
        }
        // 判断昵称是否修改
        if (!user.getNickName().equals(userUpdateBo.getNickName())) {
            if (userMapper.existsByColumn("nick_name", userUpdateBo.getNickName())) {
                throw new BusinessException("昵称已存在，请重新填写");
            }
            user.setNickName(userUpdateBo.getNickName());
        }
        // 判断学校是否存在
        if (!schoolMapper.existsByUuId(userUpdateBo.getSchoolUuid())) {
            throw new BusinessException("学校不存在，请重新选择");
        }
        user.setDisabled(userUpdateBo.getDisabled());
        user.setBackgroundImage(userUpdateBo.getBackgroundImage());
        user.setSex(userUpdateBo.getSex());
        userMapper.updateById(user);
        UserSchool userSchool = userSchoolMapper.selectOneByColumn("user_uuid", user.getUuid());
        userSchool.setSchoolUuid(userUpdateBo.getSchoolUuid());
        userSchoolMapper.updateById(userSchool);
    }

    /**
     * 重置密码
     *
     * @param uuid
     */
    @Override
    public void resetPassword(String uuid) {
        User user = userMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("用户不存在"));
        if (user.getDisabled()) {
            throw new BusinessException("用户已被禁用，不能重置密码");
        }
        if (!user.getIsSetBasicMessage()) {
            throw new BusinessException("用户未设置基本信息，不能重置密码");
        }
        // 先生成新的盐值
        String newSalt = CodecUtils.generateSalt();
        // 生成新密码
        String newPassword = CodecUtils.md5Hex(newSalt, "123456");
        user.setSalt(newSalt);
        user.setPassword(newPassword);
        userMapper.updateById(user);
        // 通知用户，密码已重置
        SystemMessageMqParamModel systemMessageMqParamModel = SystemMessageMqParamModel.builder()
            .messageType(SystemMessageType.RESET_PASSWORD)
            .receiveUserUuid(uuid)
            .content("密码重置成功，默认为123456").build();
        mqSendMessageProducer.sendSystemMessage(JSONUtil.toJsonStr(systemMessageMqParamModel));
    }

    /**
     * 组装数据 将user转换为userExcel
     *
     * @param users
     * @return
     */
    private List<UserExcel> assembleData(List<User> users) {
        return users.stream().map(user -> {
            UserExcel userExcel = BeanUtil.copyProperties(user, UserExcel.class);
            UserSchool userSchool = userSchoolMapper.selectOneByColumn("user_uuid", user.getUuid());
            if (ObjectUtil.isNotEmpty(userSchool)) {
                School school = schoolMapper.selectById(userSchool.getSchoolUuid());
                userExcel.setSchoolName(school.getName());
            }
            userExcel.setStatus(user.getDisabled() ? "禁用" : "启用");
            userExcel.setIsSetBasicMessage(user.getIsSetBasicMessage() ? "是" : "否");
            if (ObjectUtil.isNotEmpty(user.getSourceType())) {
                userExcel.setSourceType(user.getSourceType().getName());
            }
            return userExcel;
        }).collect(Collectors.toList());
    }
}
